package com.youxin.chat.pay.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.youxin.base.BaseResultCode;
import com.youxin.common.constant.RedisKey;
import com.youxin.chat.pay.context.PayPassContext;
import com.youxin.chat.pay.entity.req.TransferCodeReq;
import com.youxin.chat.pay.entity.req.TransferMoneyReq;
import com.youxin.chat.pay.entity.vo.TransferInfoVo;
import com.youxin.chat.pay.mapper.PaymentCodeMapper;
import com.youxin.chat.pay.mapper.UserWalletMapper;
import com.youxin.chat.pay.model.PaymentCode;
import com.youxin.chat.pay.model.UserWallet;
import com.youxin.chat.pay.service.TemplateService;
import com.youxin.chat.pay.service.TransferService;
import com.youxin.chat.pay.service.manager.TransferManager;
import com.youxin.chat.pay.service.rpc.UserService;
import com.youxin.chat.user.dto.UserInfoDto;
import com.youxin.exception.SystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

/**
 * description: TransferServiceImpl <br>
 * date: 2020/2/29 16:16 <br>
 * author: llkj <br>
 * version: 1.0 <br>
 */
@Service
public class TransferServiceImpl implements TransferService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private PaymentCodeMapper paymentCodeMapper;

    @Resource
    private UserWalletMapper userWalletMapper;

    @Resource
    private UserService userService;

    @Resource
    private TransferManager transferManager;

    @Resource
    private TemplateService templateService;

    @Override
    public String buildTransferCode(TransferCodeReq request) throws SystemException {
        PaymentCode paymentCode = new PaymentCode();
        if (request.getAmount() == null) {
            String code =stringRedisTemplate.opsForValue().get(RedisKey.USER_TRANSFER_GLOBAL + request.getUserNo());
            if (!StringUtils.isEmpty(code)) {
                return code;
            }
        }
        String code = generateCode();
        paymentCode.setId(code);
        paymentCode.setAmount(request.getAmount());
        paymentCode.setUserNo(request.getUserNo());
        paymentCode.setValidTime(-1L);
        paymentCode.setDeviceId(request.getDeviceId());
        paymentCode.setDeviceType(request.getDeviceType());
        paymentCode.setCreateTime(LocalDateTime.now());
        paymentCode.setRemark(request.getRemark());
        paymentCodeMapper.insert(paymentCode);
        if (request.getAmount() == null) {
            stringRedisTemplate.opsForValue().set(RedisKey.USER_TRANSFER_GLOBAL + request.getUserNo(), code, 1, TimeUnit.DAYS);
        }
        return code;
    }

    @Override
    public TransferInfoVo acquireTransferCodeInfo(String code) {
        PaymentCode paymentCode =paymentCodeMapper.selectById(code);
        if (paymentCode == null) {
            logger.error("转帐信息未找到,data={}", JSONObject.toJSONString(code));
            throw new SystemException(BaseResultCode.COMMON_FAIL, "转帐信息未找到");
        }
        UserInfoDto userInfoDto = userService.getByUserNo(paymentCode.getUserNo());
        TransferInfoVo transferInfoVo = new TransferInfoVo();
        transferInfoVo.setUserNo(userInfoDto.getUserNo());
        transferInfoVo.setAmount(paymentCode.getAmount());
        transferInfoVo.setNickName(userInfoDto.getNickName());
        transferInfoVo.setAvatar(userInfoDto.getAvatar());
        transferInfoVo.setCode(code);
        transferInfoVo.setRemark(paymentCode.getRemark());
        return transferInfoVo;
    }

    @Override
    public void transferAmount(TransferMoneyReq request) throws SystemException {
        PaymentCode paymentCode = paymentCodeMapper.selectById(request.getCode());
        if (paymentCode == null) {
            logger.error("转帐信息未找到,data={}", JSONObject.toJSONString(request));
            throw new SystemException(BaseResultCode.COMMON_FAIL, "转帐信息未找到");
        }
        UserWallet userWallet = userWalletMapper.selectUserWalleByUserNo(request.getUserNo());
        if (StringUtils.isEmpty(userWallet.getPayPwd())) {
            logger.error("支付密码未设置,userNo={}", request.getUserNo());
            throw new SystemException(BaseResultCode.PAY_PASS_NOT_SET, "支付密码未设置");
        }
        if(userWallet.getWalletStatus() != 0){
            logger.error("钱包功能被冻结,userNo={}", request.getUserNo());
            throw new SystemException(BaseResultCode.COMMON_FAIL, "用户钱包相关功能已被锁定");
        }
        logger.info("转账用户转账前余额为,userNo={},amount={}",userWallet.getUserNo(),userWallet.getUserBalance());
        boolean flag = PayPassContext.validatePass(request.getUserNo(), request.getPassword(), userWallet.getPayPwd());
        if (!flag) {
            logger.error("支付密码不正确,userNo={}", request.getUserNo());
            throw new SystemException(BaseResultCode.PASSWORD_INVALID, "支付密码不正确");
        }
        BigDecimal amount = paymentCode.getAmount();
        if(paymentCode.getAmount() == null || paymentCode.getAmount().equals(new BigDecimal(0))){
            amount = request.getAmount();
        }
        if (amount == null) {
            logger.error("转帐金额未配置,data={}", JSONObject.toJSONString(request));
            throw new SystemException(BaseResultCode.COMMON_FAIL, "转帐金额未配置");
        }
        if (request.getAmount().compareTo(new BigDecimal(0)) < 1) {
            logger.error("转账金额不能为零元,data={}", JSONObject.toJSONString(request));
            throw new SystemException(BaseResultCode.COMMON_FAIL, "转账金额不能为零元");
        }
        if (request.getUserNo().equalsIgnoreCase(paymentCode.getUserNo())) {
            logger.error("本人无法转帐到本人,data={}", JSONObject.toJSONString(request));
            throw new SystemException(BaseResultCode.COMMON_FAIL, "本人无法转帐到本人");
        }
        UserWallet payUserWallet = userWalletMapper.selectUserWalleByUserNo(paymentCode.getUserNo());
        if(payUserWallet.getWalletStatus() != 0){
            logger.error("钱包功能被冻结,userNo={}", payUserWallet.getUserNo());
            throw new SystemException(BaseResultCode.COMMON_FAIL, "付款方帐户已被锁定");
        }
        String orderNo= transferManager.transferMoney(request.getUserNo(),paymentCode.getUserNo(),amount,request.getRemark(),paymentCode.getId());
        sendTransferNotify(orderNo);
    }

    private void sendTransferNotify(String orderNo) {
        templateService.sendPaySuccMessage(orderNo);
        templateService.sendReceiveMessage(orderNo);

    }

    private static String generateCode(){
        String data = IdWorker.getIdStr();
        data = "yx" + data;
        return data;
    }
}
